package com.sprd.simple.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.sprd.simple.model.AppInfo;
import com.sprd.simple.launcher.R;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import static android.content.Context.TELEPHONY_SERVICE;

/**
 * Created by SPRD on 8/16/2016.
 */
public class PackageInfoUtil {
    public static final String PACKAGE_NAME_STK = "com.android.stk";

    private static AppInfo getAppInfo(ResolveInfo app, PackageManager pm) {
        if (app == null) {
            return null;
        }
        AppInfo appInfo = new AppInfo();
        appInfo.setAppLabel((String) app.loadLabel(pm));
        appInfo.setAppIcon(app.loadIcon(pm));
        appInfo.setAppPkg(app.activityInfo.packageName);
        return appInfo;
    }

    /**
     * Find all applications that hold the launcher attribution.
     *
     * @param context
     * @return all apps that hold the launcher attribution.
     */
    public static List<ResolveInfo> getAllLauncherAttrApplication(Context context) {
        Intent intent = new Intent(Intent.ACTION_MAIN, null);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, 0);
        Collections.sort(resolveInfos, new ResolveInfo.DisplayNameComparator(context.getPackageManager()));
        return resolveInfos;
    }

    /**
     * Only for appfolder, find all applications that hold the launcher attribution.
     *
     * @param context
     * @return all apps For AppFolder.
     */
    public static List<AppInfo> getLauncherAttrAppForAppFolder(Context context) {
        List<ResolveInfo> resolveInfos = getAllLauncherAttrApplication(context);

        // add the stk apk.
        if (!isAirplaneModeOn(context) && !hasExistSimCard(context)) {
            ResolveInfo info = findAppInfoByPackageName(context, PACKAGE_NAME_STK);
            if (info != null) {
                resolveInfos.add(info);
            }
        }

        // find all apps on desktop and tools, then add to set.
        Set<String> notNeedExistAppFolder = new HashSet<>();
        notNeedExistAppFolder.addAll(getDesktopApps(context));
        notNeedExistAppFolder.addAll(getToolApps(context));

        // remove those apks which they do not need to show in appFolder.
        return getAppsByFilter(context, resolveInfos, notNeedExistAppFolder);
    }

    /**
     * Find all apk on desktop
     *
     * @param context
     * @return DesktopApps
     */
    public static Set<String> getDesktopApps(Context context) {
        SharedPreferences sharedPreferences = context.getSharedPreferences(HomeConstants.SP_NAME, Context.MODE_PRIVATE);
        Set<String> packageNameSet = sharedPreferences.getStringSet(HomeConstants.HOME_APPS_NAMES, null);
        if (packageNameSet == null) {
            packageNameSet = new HashSet<>();
        }
        // add self to set
        packageNameSet.add(context.getPackageName());
        return packageNameSet;
    }

    /**
     * Find all apk in toolFolder.
     *
     * @param context
     * @return ToolApps
     */
    public static List<String> getToolApps(Context context) {
        String[] toolApps = context.getResources().getStringArray(R.array.tool_apps);
        return Arrays.asList(toolApps);
    }

    /**
     * remove those apks which they do not need to show in appFolder.
     *
     * @param context
     * @param sources
     * @param needRemoveSet
     * @return apps after filter
     */
    private static List<AppInfo> getAppsByFilter(Context context, List<ResolveInfo> sources,
            Set<String> needRemoveSet) {
        List<AppInfo> appInfos = new ArrayList<>();
        for (ResolveInfo app : sources) {
            if (app == null) {
                continue;
            }
            if (!needRemoveSet.contains(app.activityInfo.packageName)) {
                AppInfo appInfo = getAppInfo(app, context.getPackageManager());
                if (appInfo != null) {
                    appInfos.add(appInfo);
                }
            }
        }
        return appInfos;
    }

    /**
     * judge airplane mode. 0 is on, 1 is off.
     *
     * @param context
     * @return true is on, or off.
     */
    public static boolean isAirplaneModeOn(Context context) {
        return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0;
    }

    /**
     * Find app by packageName only.
     *
     * @param context
     * @param packageName
     * @return ResolveInfo
     */
    private static ResolveInfo findAppInfoByPackageName(Context context, String packageName) {
        Intent intent = new Intent();
        intent.setPackage(packageName);
        List<ResolveInfo> tempAllApps = context.getPackageManager().queryIntentActivities(intent, 0);
        return tempAllApps != null ? tempAllApps.get(0) : null;
    }

    /**
     * To determine whether the Sim card has been inserted.
     *
     * @param context
     * @return if has been inserted, return true.
     */
    public static boolean hasExistSimCard(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(TELEPHONY_SERVICE);
        String simSerialNumber = tm != null ? tm.getSimSerialNumber() : "";
        if (TextUtils.isEmpty(simSerialNumber)) {
            return false;
        }
        return true;
    }
}
